Skip to content

fix(cost-check): metering tar 单 pattern 终修(#258,ADR-0083 关联) - #340

Closed
randypanding wants to merge 10 commits into
mainfrom
fix/cost-check-tar-single-pattern
Closed

fix(cost-check): metering tar 单 pattern 终修(#258,ADR-0083 关联)#340
randypanding wants to merge 10 commits into
mainfrom
fix/cost-check-tar-single-pattern

Conversation

@randypanding

@randypanding randypanding commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

动机

两轮实测定位:tar 多 pattern 任一未命中即 exit 2——"records-*.jsonl" 裸兜底模式在带目录前缀的 tarball 里恒未命中,连累命中的 "*/records-*.jsonl" 整体判失败 → cost-check 恒 INFRA。

测试

本地实测:单 pattern 提取 metering-ledger tarball 成功(records-2026-W34/W35 落盘)。

Card: #263
Ref: ADR-0083

Summary by CodeRabbit

  • 新功能

    • 新增合并队列与跨仓审计结果校验,验证通过后显示安全检查结果。
    • 新增规范变更检测与自动测试门禁,确保相关测试套件完整且执行成功。
  • 错误修复

    • 修复计量记录归档读取失败问题。
    • 改进治理接口异常处理,避免无效响应被误判为正常状态。
  • 治理与测试

    • 更新分支保护及必需工作流配置。
    • 新增治理规则、预期状态与审计工件的验收测试。
    • 调整定时检查执行时间。

randypanding and others added 10 commits August 22, 2026 12:58
 C6-a, ADR-0021)

hygiene.yml@9c20d43... no longer matches any v1 tag (v1 now points to
61191f87c537f6e887695517121c6e530a838261). Refresh pin to current v1 target.
Reference: template-service PR #39 same fix pattern.

Card: #259
Ref: ADR-0021
…thub#275,ADR-0083)

- gate.yml 新增 t14-spec-suite job:specs/** PR 必含含断言的 suite/(fail-closed);
  全部 specs/*/suite 在 CI 真实执行(可执行性证明)
- specs/ISSUE-263/suite/:IR 自有验收套件(9 项断言——T5/T6、T-14/T-15、AR-10、
  ruleset adversary 无 integration_id、verifier_app 登记、holdout 申报;自反断言)
- main-protection.json 剔除 adversary 条目非法 integration_id:0(致 apply 422、
  线上 ruleset 长期缺 adversary——独立验证发现的断链根因)
- drift-check §1 fail-closed:ruleset 清单非数组 → FATAL exit 2(GOVERNANCE_TOKEN
  失效期间曾把四个真实 ruleset 全报『不存在』)
- g060-guard cron 错峰(0 → 17 分,对齐 workflow 规范)
…adversary check 永缺(队列 60min 超时弹回根因)
…运行致条目恒挂(#95 实测),结构性冲突先摘除(ADR-0083 关联)
…rg-gate job 对中心仓自跳,required 化后产生永不满足的 skipped)+ 钉点 ref=main(SHA 形式被 ruleset API 拒绝)
…实测);expected-state/W1-C5 自检同步;adversary-gate 纳入钉点面
Copilot AI lite review requested due to automatic review settings August 24, 2026 04:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b03f67de-7b6f-477d-827a-dee1b62e30ef

📥 Commits

Reviewing files that changed from the base of the PR and between 5dbc0aa and 969f7b1.

⛔ Files ignored due to path filters (1)
  • specs/ISSUE-263/suite/__pycache__/test_ir263_artifacts.cpython-311.pyc is excluded by !**/*.pyc
📒 Files selected for processing (11)
  • .github/workflows/adversary-gate.yml
  • .github/workflows/adversary-relay.yml
  • .github/workflows/g060-guard.yml
  • .github/workflows/gate.yml
  • governance/cost-check.sh
  • governance/drift-check.sh
  • governance/expected-state.json
  • governance/rulesets/main-protection.json
  • governance/rulesets/org-required-workflows.json
  • governance/tests/test-issue263-w1c5.sh
  • specs/ISSUE-263/suite/test_ir263_artifacts.py

📝 Walkthrough

Walkthrough

本次变更更新 adversary 门禁、跨仓审计 relay、spec 套件校验、治理规则及治理脚本,并调整定时任务。

Changes

治理门禁

Layer / File(s) Summary
adversary 门禁与跨仓核证
.github/workflows/adversary-gate.yml, .github/workflows/adversary-relay.yml
merge queue 按 specs/** 变更执行 fail-closed 判断。relay workflow 核证跨仓审计 run 后写入 adversary 成功 check。
spec 套件门禁
.github/workflows/gate.yml
新增 t14-spec-suite job。该 job 校验变更 specs 目录的测试套件,并执行全部 unittest 测试。
治理状态与规则同步
governance/expected-state.json, governance/rulesets/*.json, governance/tests/test-issue263-w1c5.sh, specs/ISSUE-263/suite/test_ir263_artifacts.py
治理工作流引用改为 main,加入 adversary-gate.yml,移除 merge_queue 配置,并新增对应工件验证。
治理脚本与定时任务
governance/cost-check.sh, governance/drift-check.sh, .github/workflows/g060-guard.yml
修复 ledger 文件匹配模式。rulesets API 返回非数组时终止检查。定时任务改为每六小时第 17 分钟运行。

Suggested labels: security, bug, feature

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cost-check-tar-single-pattern

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added bug Something isn't working feature security labels Aug 24, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix metering tar extraction and harden governance gates (ADR-0083)

🐞 Bug fix ✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Fix cost-check metering ledger tar extraction by correcting wildcard patterns.
• Harden governance CI: enforce specs/** suites (T-14) and fail-closed on API blindness.
• Make adversary required-check resilient: support merge queue and cross-repo relay.
Diagram

graph TD
  E["GitHub events"] --> G["gate.yml (T-14)"] --> S["specs/*/suite"]
  E --> AG["adversary-gate.yml"] --> API{{"GitHub API (compare/checks/actions)"}}
  E --> AR["adversary-relay.yml"] --> API
  GS("governance scripts") --> ST[("expected-state & rulesets")] --> API

  subgraph Legend
    direction LR
    _wf["Workflow"] ~~~ _sh("Shell/script") ~~~ _st[("State/rules") ] ~~~ _api{{"GitHub API"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Automate cross-repo relay via workflow_run/event-driven bridge
  • ➕ Removes manual workflow_dispatch step and reduces human error in supplying run_id/head_sha
  • ➕ Enables deterministic linking between CI-Workflows audit completion and check write-back
  • ➖ Requires additional permission modeling across repos; may reintroduce token/identity complexity
  • ➖ More moving parts if GitHub events/log access are flaky
2. Verify audit result via structured artifact/API field instead of log-grep
  • ➕ More robust than grepping logs (log truncation/format changes)
  • ➕ Clearer contract: e.g., JSON artifact with adversary-report/v1 verdict
  • ➖ Requires CI-Workflows adversary pipeline changes to publish/retain the artifact reliably
  • ➖ Adds coupling between repos on report schema and retention
3. Preflight tar members then extract exact paths (avoid wildcard pitfalls)
  • ➕ Avoids fragile multi-pattern tar semantics and strip-components interactions
  • ➕ Easier to debug: list members, then extract exactly one resolved match
  • ➖ Slightly more code and I/O (tar -t then tar -x)
  • ➖ Needs careful handling when multiple matches are legitimate

Recommendation: Overall approach is sound: make required-check plumbing resilient (merge_group support, remove App-token SPOF, fail-closed on API blindness) and fix the metering tar pattern at the source. Two follow-ups worth considering: (1) avoid log-grep verification by consuming a structured audit artifact, and (2) remove the committed pycache/*.pyc from specs (binary build artifact) to keep suites reviewable and deterministic.

Files changed (12) +566 / -265

Bug fix (3) +13 / -3
cost-check.shFix metering ledger tar extraction wildcard for directory-prefixed members +4/-1

Fix metering ledger tar extraction wildcard for directory-prefixed members

• Updates tar wildcard patterns to match members stored under a top-level directory (e.g., <repo>-<sha>/records-*.jsonl) when using --strip-components=1. Prevents false INFRA classification caused by an always-missing fallback glob.

governance/cost-check.sh

drift-check.shFail-closed when org rulesets API response is not an array +8/-0

Fail-closed when org rulesets API response is not an array

• Adds a guard that treats non-array responses (token expiry, network failure, permission loss) as fatal and exits 2. Prevents drift-check from producing misleading "ruleset不存在" results when the detector is blind.

governance/drift-check.sh

main-protection.jsonRemove invalid integration_id from adversary required check entry +1/-2

Remove invalid integration_id from adversary required check entry

• Drops integration_id:0 for the adversary required status check context, preventing ruleset apply failures (HTTP 422) and aligning with required-check semantics.

governance/rulesets/main-protection.json

Tests (2) +116 / -9
test-issue263-w1c5.shUpdate governance test expectations for branch-pinned required workflows +11/-9

Update governance test expectations for branch-pinned required workflows

• Replaces assertions that required-workflows refs are 40-char SHAs with assertions that refs are branch names (main/master). Adds checks that both org-gate.yml and adversary-gate.yml are present, and asserts ref_commit is removed from expected-state.

governance/tests/test-issue263-w1c5.sh

test_ir263_artifacts.pyAdd ISSUE-263 governance acceptance suite (unittest, zero deps) +105/-0

Add ISSUE-263 governance acceptance suite (unittest, zero deps)

• Introduces a self-contained unittest suite asserting key governance artifacts and ruleset constraints (T5/T6 registration, T-14/T-15/AR-10 clauses, adversary required check shape, verifier_app registration). Includes a self-test ensuring the suite contains a meaningful number of assertions to avoid empty/"摆拍" tests.

specs/ISSUE-263/suite/test_ir263_artifacts.py

Other (7) +437 / -253
adversary-gate.ymlSupport merge_group and remove App-token dependency for adversary check +45/-27

Support merge_group and remove App-token dependency for adversary check

• Adds merge_group trigger handling to prevent merge-queue entries from timing out due to missing adversary checks. Replaces the GitHub App token path with job-scoped github.token for reading/writing check-runs, removing a secret-based single point of failure.

.github/workflows/adversary-gate.yml

adversary-relay.ymlAdd cross-repo adversary verdict relay workflow (mechanically verified) +91/-0

Add cross-repo adversary verdict relay workflow (mechanically verified)

• Introduces a manual workflow_dispatch that verifies an external CI-Workflows adversary run is completed/success and contains a survived verdict line before writing a success adversary check-run to this repo. Designed as fail-closed: any mismatch or API failure prevents writing success.

.github/workflows/adversary-relay.yml

g060-guard.ymlStagger scheduled g060-guard cron to minute 17 +1/-1

Stagger scheduled g060-guard cron to minute 17

• Moves the 6-hour cron schedule off minute 0 to reduce contention and align with workflow scheduling conventions.

.github/workflows/g060-guard.yml

gate.ymlAdd T-14 specs suite enforcement and execution job +82/-0

Add T-14 specs suite enforcement and execution job

• Adds a t14-spec-suite job that fail-closed enforces specs/** PRs to include a non-empty suite/ with real assertions, using the PR files API with pagination. Executes all specs/*/suite via unittest discover to prove suite executability and prevent "摆拍" suites.

.github/workflows/gate.yml

expected-state.jsonUpdate expected governance state for required workflows + remove merge_queue +213/-222

Update expected governance state for required workflows + remove merge_queue

• Documents removal of merge_queue due to platform/required-check incompatibility and updates org_required_workflows to pin to branch ref (main) and include adversary-gate. Removes obsolete ref_commit pinning and adds rationale about platform rejecting SHA refs.

governance/expected-state.json

org-required-workflows.jsonAdjust required workflows ruleset: exclude CI-Workflows and pin ref to main +5/-3

Adjust required workflows ruleset: exclude CI-Workflows and pin ref to main

• Excludes CI-Workflows from org-required-workflows to avoid permanent skipped required workflows on the central repo. Updates required workflow refs from a commit SHA to main due to platform constraints, and keeps org-gate + adversary-gate listed.

governance/rulesets/org-required-workflows.json

test_ir263_artifacts.cpython-311.pycAdd compiled Python bytecode artifact in suite cache +0/-0

Add compiled Python bytecode artifact in suite cache

• Adds a __pycache__ .pyc file to the repo, which is typically a local build artifact rather than source. This may be accidental and can create noisy diffs and non-determinism across Python versions.

specs/ISSUE-263/suite/pycache/test_ir263_artifacts.cpython-311.pyc

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (6) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Tar 多 pattern 仍失败 🐞 Bug ≡ Correctness
Description
governance/cost-check.sh 仍在同一次 tar 解包里传入两个 pattern;当第二个 pattern("records-*.jsonl")未命中时,tar
仍会以错误状态退出,导致整个解包被判 INFRA。该 PR 的根因叙述就是“任一未命中即 exit 2”,所以当前改动仍可能在“仅带前缀目录”的 tarball 上复现。
Code

governance/cost-check.sh[R169-170]

    if ! tar -xzf "$led.tar.gz" -C "$led" --strip-components=1 --wildcards \
-         "*-records-*.jsonl" "records-*.jsonl" 2>/dev/null; then
+         "*/records-*.jsonl" "records-*.jsonl" 2>/dev/null; then
Relevance

●●● Strong

直接延续本 PR 明确的 tar 多 pattern 根因,属于可复现的局部正确性缺陷。

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR 修改后仍在同一次 tar 命令中传入两个通配 pattern;tar 对“请求成员未找到”会以失败状态结束(常见 exit=2),这与 PR 描述的根因一致,因此仍可能把成功提取误判为失败。

governance/cost-check.sh[163-172]
🌐 示例表明当请求的成员未在归档中找到时 tar 会报 “Not found in archive” 并以退出码 2 失败;除非使用忽略缺失成员的行为/选项。

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`tar -x ... pattern1 pattern2` 在任一 pattern 未命中时可能返回非 0(常见为 2),从而让“命中的文件也被整体判失败”。当前代码仍传入两个 pattern("*/records-*.jsonl" 和 "records-*.jsonl"),与 PR 描述中的根因(任一未命中即 exit 2)相矛盾。

### Issue Context
目标是兼容两类 tarball:
- 形如 `<repo>-<sha>/records-*.jsonl`(需要 `*/records-*.jsonl`)
- 形如 `records-*.jsonl`(不带目录前缀)

### Fix Focus Areas
- governance/cost-check.sh[163-172]

### Proposed fix
把一次 tar 调用拆成两次“单 pattern”尝试(或启用能忽略未命中的 tar 选项/行为),例如:
1) 先尝试 `tar ... "*/records-*.jsonl"`
2) 若失败再尝试 `tar ... "records-*.jsonl"`
并确保只有在两次都失败时才判 INFRA。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. drift-check 恒报钉点漂移 🐞 Bug ≡ Correctness
Description
expected-state.json 删除 org_required_workflows.ref_commit 并将 ref 改为分支名后,governance/drift-check.sh
仍无条件读取 .ref_commit 并做“钉点移动”比较;由于 WANT_COMMIT 会变成 null,drift-check 会把任何正常状态都判为漂移。
Code

governance/expected-state.json[R201-204]

+    "repository_id": 1337911551,
+    "path": ".github/workflows/org-gate.yml",
+    "ref": "main",
+    "workflows": [
Relevance

●●● Strong

expected-state 已移除 ref_commit,而定位描述 drift-check 仍无条件读取,属于明确的契约不一致。

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
expected-state 已改为仅提供 ref=main 且移除 ref_commit;但 drift-check 仍要求 ref_commit 并将其参与漂移判定,从代码路径可推导出
WANT_COMMIT 为 null 时必然触发漂移。

governance/expected-state.json[197-212]
governance/drift-check.sh[684-732]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`expected-state.json` 中 `org_required_workflows` 已不再包含 `ref_commit`,但 `drift-check.sh` §15 仍执行 `WANT_COMMIT=$(jq -r '.ref_commit' ...)` 并用它与解引用得到的 commit SHA 比较。字段缺失时 `jq -r` 返回 `null`,导致比较恒不相等,从而把 org-required-workflows 误判为“钉点已移动”。

### Issue Context
PR 注释称“内容完整性改由 drift-check 后验承载”,但 drift-check 目前实现仍依赖 `ref_commit`。

### Fix Focus Areas
- governance/drift-check.sh[684-732]
- governance/expected-state.json[197-212]

### Proposed fix
调整 drift-check §15:
- 若 expected-state 不提供 `ref_commit`(或 `ref` 不是 tag/SHA 而是分支名),则不要做 commit-binding 比较;改为:
 - 仅校验 ruleset 的 path/ref/repository_id/workflows 列表一致;并
 - (可选)从分支 ref 解引用到当前 commit,但仅作为信息输出,不作为“移动”漂移判断,或引入新的、可行的完整性机制(例如对 CI-Workflows 工作流文件内容做哈希对账)。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Compare 文件数截断误放行 🐞 Bug ⛨ Security
Description
merge_group 路径用 compare API 的 .files 判断是否改动 specs/**,但该接口的 changed files 最多只返回 300
个文件;当改动文件数超过上限时可能漏掉 specs/** 变更并错误写回 adversary success。这样会把本应 fail-closed 的合并错误放行。
Code

.github/workflows/adversary-gate.yml[R55-63]

+          FILES=$(gh api "repos/$REPO/compare/$BASE_SHA...$HEAD_SHA" --jq '[.files[].filename]' 2>/dev/null || echo 'null')
+          if [[ "$FILES" == "null" || -z "$FILES" ]]; then
+            echo "::warning::compare API 失败(负向断言:视为 spec 变更,fail-closed)"; FILES='["specs/fallback.md"]'
+          fi
+          HASSPECS=$(echo "$FILES" | python3 -c "import json,sys;files=json.load(sys.stdin);print('true' if any(f.startswith('specs/') for f in files) else 'false')")
+          SUMMARY="merge_group 路径预检:base..head specs/** 变更=$HASSPECS"
+          if [[ "$HASSPECS" == "true" ]]; then
+            echo "::error::merge queue 提交含 specs/** 变更——需人工确认 survived 审计后重试(fail-closed)"
+            exit 1
Evidence
代码在 merge_group 路径用 compare API 的 .files 列表做唯一判据;GitHub 文档明确该 endpoint 在分页场景下 changed files
仅在第一页展示且最多包含 300 个文件,因此文件级判断会出现漏检。此类“文件列表只取部分”绕过在本仓曾作为真实缺陷出现过。

.github/workflows/adversary-gate.yml[46-64]
🌐 Compare two commits 文档的 Working with large comparisons 说明:changed files 只在第一页展示,并且整个比较最多包含 300 个 changed files。
PR-#19

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`GET /compare/{base}...{head}` 的响应里 `.files` 在大比较下会被截断(最多 300 个 changed files),当前逻辑只基于 `.files[].filename` 是否以 `specs/` 开头来决定放行/阻断。若 specs 变更落在被截断部分,将被误判为“无 specs 变更”并直接写回 success check。

### Issue Context
此 gate 被设计为 fail-closed;任何“文件清单不完整”的路径判断都会变成可绕过点。

### Fix Focus Areas
- .github/workflows/adversary-gate.yml[55-64]

### Proposed fix
不要用 compare API 的 `.files` 作为唯一来源。可选方案:
1) checkout + fetch base/head 后用 `git diff --name-only $BASE_SHA $HEAD_SHA`(全量、无 300 限制);或
2) 若继续用 compare API:显式检测“可能截断”的条件并 fail-closed(例如 `.files|length == 300` 时直接按 specs 变更处理),同时记录告警。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (1)
4. 跨仓 relay 永远 404 🐞 Bug ☼ Reliability
Description
adversary-relay.yml 用本仓 github.token 通过 gh api/gh run view 读取 Cloudbird-Software/CI-Workflows 的
Actions run 信息,但 GITHUB_TOKEN 默认只能访问当前工作流所在仓库资源。若 CI-Workflows 为私有仓(或未对该 token 授权),该 workflow
会稳定失败并无法写回 survived check。
Code

.github/workflows/adversary-relay.yml[R41-52]

+        env:
+          GH_TOKEN: ${{ github.token }}
+          AUDIT_RUN_ID: ${{ github.event.inputs.audit_run_id }}
+          AUDIT_REPO: ${{ github.event.inputs.audit_repo || 'Cloudbird-Software/CI-Workflows' }}
+          PR_NUMBER: ${{ github.event.inputs.pr_number }}
+          HEAD_SHA: ${{ github.event.inputs.head_sha }}
+          AUDIT_HEAD_NOTE: ${{ github.event.inputs.audit_head_note }}
+        run: |
+          set -euo pipefail
+          # 1) 审计 run 存在 + 绿
+          RUN=$(gh api "repos/$AUDIT_REPO/actions/runs/$AUDIT_RUN_ID" 2>/dev/null) \
+            || { echo "::error::审计 run $AUDIT_RUN_ID 不存在(fail-closed)"; exit 1; }
Relevance

●● Moderate

跨仓访问风险具体且合理,但历史证据仅拒绝泛化的 App-token 改造,情境并非完全相同。

PR-#336
PR-#195

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
代码明确用 github.token 读取另一个仓库(AUDIT_REPO 默认 CI-Workflows)的 Actions run;GitHub 文档明确 GITHUB_TOKEN
仅能访问当前仓库资源,因此在常见私有仓场景会直接 404/403。

.github/workflows/adversary-relay.yml[40-63]
🌐 文档明确说明:内置 GITHUB_TOKEN 只能访问工作流所在仓库的资源;若需访问组织或其他仓库资源,应使用 GitHub App 等额外凭据。

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
workflow 期望跨仓读取 CI-Workflows 的 run(`gh api repos/$AUDIT_REPO/...` / `gh run view -R $AUDIT_REPO`),但当前仅配置了 `${{ github.token }}`。GitHub 官方文档指出 `GITHUB_TOKEN` 只能访问 workflow 所在仓库的资源,跨仓访问需要 GitHub App 安装 token 或更宽权限的凭据。

### Issue Context
该 relay 是 specs PR 的“survived 背书”写回路径;若跨仓读取始终失败,会导致 specs PR 永远无法满足 required adversary check(实际变成永久 fail-closed)。

### Fix Focus Areas
- .github/workflows/adversary-relay.yml[40-63]

### Proposed fix
引入可跨仓读取 CI-Workflows 的最小权限凭据:
- 优先:GitHub App installation token(限制仅 CI-Workflows actions:read + 本仓 checks:write)
- 备选:fine-grained PAT(同样限制仓库范围与 actions:read)
并将该 token 用于 gh/curl 调用 `$AUDIT_REPO` 的读取接口。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Workflows use ${{ github.token }} 📘 Rule violation ⛨ Security
Description
New GitHub API calls in workflows authenticate directly with the built-in github.token /
GH_TOKEN rather than obtaining a constrained cloudbrid-agent GitHub App token via scripts/ghcb
or scripts/gh-app-token.sh. This can violate the repository’s agent/automation credential standard
and makes it harder to enforce uniform scope/TTL constraints.
Code

.github/workflows/adversary-gate.yml[R49-52]

+          GH_TOKEN: ${{ github.token }}
+          REPO: ${{ github.repository }}
+          HEAD_SHA: ${{ github.event.merge_group.head_sha }}
+          BASE_SHA: ${{ github.event.merge_group.base_sha }}
Relevance

● Weak

团队在同一 PR 明确拒绝将 github.token 替换为 App token,认可 job 权限足够。

PR-#336

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2778539 requires GitHub API operations in repo automation to authenticate via the
approved cloudbrid-agent app token flow (scripts/ghcb / scripts/gh-app-token.sh) rather than
using GITHUB_TOKEN/github.token directly. The added/modified workflow steps set
GH_TOKEN/GATE_TOKEN to ${{ github.token }} and then call gh api/curl against
api.github.com to read/write check-runs.

Rule 2778539: Agent GitHub operations must use cloudbrid-agent app tokens with constrained scope
.github/workflows/adversary-gate.yml[49-56]
.github/workflows/adversary-gate.yml[133-140]
.github/workflows/adversary-relay.yml[41-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Workflows performing GitHub API operations are using `github.token` (`GH_TOKEN`) directly. Compliance requires agent/automation GitHub operations to use `cloudbrid-agent` app tokens with constrained scope and short TTL via the approved wrappers/scripts.

## Issue Context
This PR adds/changes multiple `.github/workflows/*` steps that call `gh api` and `curl https://api.github.com/...` while authenticating with `github.token`.

## Fix Focus Areas
- .github/workflows/adversary-gate.yml[49-56]
- .github/workflows/adversary-gate.yml[133-140]
- .github/workflows/adversary-relay.yml[41-52]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. merge_group 并发组键为空 🐞 Bug ☼ Reliability
Description
adversary-gate.yml 新增 merge_group 触发后,workflow 的 concurrency.group 仍使用
github.event.pull_request.number;在 merge_group 事件中该字段不存在,导致 group 退化为同一个固定值,所有 merge queue
构建会串行排队并可能造成超时。
Code

.github/workflows/adversary-gate.yml[R21-26]

+  merge_group:
+    # merge queue 兼容(2026-08-24):required workflow 不在队列分支上自动运行,
+    # 队列 merge commit 会永远等不到 adversary check(60min 超时弹回)——本 gate
+    # 在 checks_requested 时对比 base..head,无 specs/** 变更即写 success(与
+    # PR 路径同语义);有 specs 变更的合并需人工补 survived 审计(fail-closed)。
+    types: [checks_requested]
Relevance

● Weak

同一 PR 的 merge_group concurrency 及检查写回缺陷已被团队明确拒绝。

PR-#336

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR 引入 merge_group 触发,但 concurrency 仍绑定 pull_request.number;GitHub 文档说明 merge_group 的关键字段是
head_sha/base_sha,且作为独立事件触发 required checks。

.github/workflows/adversary-gate.yml[18-36]
🌐 文档说明 merge_group 事件用于 merge queue required checks,payload 关键字段为 head SHA(用于校验与上报 status/checks),它是独立于 pull_request 的事件。

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
新增 `merge_group` 触发后,该 workflow 仍用 `github.event.pull_request.number` 作为 concurrency key。`merge_group` payload 不包含 `pull_request.number`,会导致 concurrency group 变成固定字符串(或空值拼接),从而让所有 merge queue 的 adversary-gate 互相串行阻塞。

### Issue Context
merge queue 依赖 required checks 在队列分支上及时完成;串行排队会显著放大等待时间并引发 60min 超时弹回(与 PR 注释场景相同)。

### Fix Focus Areas
- .github/workflows/adversary-gate.yml[21-35]

### Proposed fix
把 concurrency.group 改为按事件类型分流:
- pull_request:使用 PR number
- merge_group:使用 `github.event.merge_group.head_sha`(或 `github.sha`)
示例:
`group: adversary-gate-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.event.merge_group.head_sha }}`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. 提交了 Python .pyc 🐞 Bug ⚙ Maintainability
Description
PR 直接加入了
specs/ISSUE-263/suite/__pycache__/test_ir263_artifacts.cpython-311.pyc,这类字节码文件是运行时生成物,会造成无意义的 diff
噪声并可能引入平台/版本相关的仓库污染。该仓 gate 会执行 unittest,从而在 CI 环境再次生成/覆盖此类文件。
Code

specs/ISSUE-263/suite/pycache/test_ir263_artifacts.cpython-311.pyc[1]

+
Relevance

● Weak

同一 PR 对该精确 pyc 构建产物清理建议已明确拒绝。

PR-#336

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR 新增了 __pycache__/*.pyc 文件,同时 gate job 会运行 unittest(会生成同类缓存文件),因此该二进制文件属于可再生构建产物,留在仓库只会制造噪声与污染。

.github/workflows/gate.yml[92-104]
specs/ISSUE-263/suite/test_ir263_artifacts.py[1-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`.pyc`/`__pycache__` 属于 Python 运行时缓存,不应进入版本控制;会导致仓库包含二进制噪声、并引发不同 Python 版本/平台下的频繁变更。

### Issue Context
本仓 gate job 会执行 `python3 -m unittest discover`,运行后本就会生成 `__pycache__`。

### Fix Focus Areas
- specs/ISSUE-263/suite/__pycache__/test_ir263_artifacts.cpython-311.pyc[1-1]
- .github/workflows/gate.yml[92-104]

### Proposed fix
1) 从 PR 中移除该 `.pyc` 文件;
2) 添加忽略规则(例如新增 `.gitignore`,包含 `__pycache__/`、`*.pyc`、`*.pyo` 等),避免后续再误提交。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 18 rules
✅ Web pages:
  +17 more
Review mode: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 16/18, lines 831/200; both must reach the floor). Router rationale: 该 PR 同时修改多条 GitHub Actions 治理/权限与跨仓中继路径、规则集契约、漂移检测、tar 解包逻辑及测试,涉及多个相互独立且易漏检的行为点,单次审查可能遗漏缺陷。
ⓘ  4 issues published inline · 7 in summary

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread governance/cost-check.sh
Comment on lines 169 to +170
if ! tar -xzf "$led.tar.gz" -C "$led" --strip-components=1 --wildcards \
"*-records-*.jsonl" "records-*.jsonl" 2>/dev/null; then
"*/records-*.jsonl" "records-*.jsonl" 2>/dev/null; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Tar 多 pattern 仍失败 🐞 Bug ≡ Correctness

governance/cost-check.sh 仍在同一次 tar 解包里传入两个 pattern;当第二个 pattern("records-*.jsonl")未命中时,tar
仍会以错误状态退出,导致整个解包被判 INFRA。该 PR 的根因叙述就是“任一未命中即 exit 2”,所以当前改动仍可能在“仅带前缀目录”的 tarball 上复现。
Agent Prompt
### Issue description
`tar -x ... pattern1 pattern2` 在任一 pattern 未命中时可能返回非 0(常见为 2),从而让“命中的文件也被整体判失败”。当前代码仍传入两个 pattern("*/records-*.jsonl" 和 "records-*.jsonl"),与 PR 描述中的根因(任一未命中即 exit 2)相矛盾。

### Issue Context
目标是兼容两类 tarball:
- 形如 `<repo>-<sha>/records-*.jsonl`(需要 `*/records-*.jsonl`)
- 形如 `records-*.jsonl`(不带目录前缀)

### Fix Focus Areas
- governance/cost-check.sh[163-172]

### Proposed fix
把一次 tar 调用拆成两次“单 pattern”尝试(或启用能忽略未命中的 tar 选项/行为),例如:
1) 先尝试 `tar ... "*/records-*.jsonl"`
2) 若失败再尝试 `tar ... "records-*.jsonl"`
并确保只有在两次都失败时才判 INFRA。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +55 to +63
FILES=$(gh api "repos/$REPO/compare/$BASE_SHA...$HEAD_SHA" --jq '[.files[].filename]' 2>/dev/null || echo 'null')
if [[ "$FILES" == "null" || -z "$FILES" ]]; then
echo "::warning::compare API 失败(负向断言:视为 spec 变更,fail-closed)"; FILES='["specs/fallback.md"]'
fi
HASSPECS=$(echo "$FILES" | python3 -c "import json,sys;files=json.load(sys.stdin);print('true' if any(f.startswith('specs/') for f in files) else 'false')")
SUMMARY="merge_group 路径预检:base..head specs/** 变更=$HASSPECS"
if [[ "$HASSPECS" == "true" ]]; then
echo "::error::merge queue 提交含 specs/** 变更——需人工确认 survived 审计后重试(fail-closed)"
exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Compare 文件数截断误放行 🐞 Bug ⛨ Security

merge_group 路径用 compare API 的 .files 判断是否改动 specs/**,但该接口的 changed files 最多只返回 300
个文件;当改动文件数超过上限时可能漏掉 specs/** 变更并错误写回 adversary success。这样会把本应 fail-closed 的合并错误放行。
Agent Prompt
### Issue description
`GET /compare/{base}...{head}` 的响应里 `.files` 在大比较下会被截断(最多 300 个 changed files),当前逻辑只基于 `.files[].filename` 是否以 `specs/` 开头来决定放行/阻断。若 specs 变更落在被截断部分,将被误判为“无 specs 变更”并直接写回 success check。

### Issue Context
此 gate 被设计为 fail-closed;任何“文件清单不完整”的路径判断都会变成可绕过点。

### Fix Focus Areas
- .github/workflows/adversary-gate.yml[55-64]

### Proposed fix
不要用 compare API 的 `.files` 作为唯一来源。可选方案:
1) checkout + fetch base/head 后用 `git diff --name-only $BASE_SHA $HEAD_SHA`(全量、无 300 限制);或
2) 若继续用 compare API:显式检测“可能截断”的条件并 fail-closed(例如 `.files|length == 300` 时直接按 specs 变更处理),同时记录告警。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +41 to +52
env:
GH_TOKEN: ${{ github.token }}
AUDIT_RUN_ID: ${{ github.event.inputs.audit_run_id }}
AUDIT_REPO: ${{ github.event.inputs.audit_repo || 'Cloudbird-Software/CI-Workflows' }}
PR_NUMBER: ${{ github.event.inputs.pr_number }}
HEAD_SHA: ${{ github.event.inputs.head_sha }}
AUDIT_HEAD_NOTE: ${{ github.event.inputs.audit_head_note }}
run: |
set -euo pipefail
# 1) 审计 run 存在 + 绿
RUN=$(gh api "repos/$AUDIT_REPO/actions/runs/$AUDIT_RUN_ID" 2>/dev/null) \
|| { echo "::error::审计 run $AUDIT_RUN_ID 不存在(fail-closed)"; exit 1; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. 跨仓 relay 永远 404 🐞 Bug ☼ Reliability

adversary-relay.yml 用本仓 github.token 通过 gh api/gh run view 读取 Cloudbird-Software/CI-Workflows 的
Actions run 信息,但 GITHUB_TOKEN 默认只能访问当前工作流所在仓库资源。若 CI-Workflows 为私有仓(或未对该 token 授权),该 workflow
会稳定失败并无法写回 survived check。
Agent Prompt
### Issue description
workflow 期望跨仓读取 CI-Workflows 的 run(`gh api repos/$AUDIT_REPO/...` / `gh run view -R $AUDIT_REPO`),但当前仅配置了 `${{ github.token }}`。GitHub 官方文档指出 `GITHUB_TOKEN` 只能访问 workflow 所在仓库的资源,跨仓访问需要 GitHub App 安装 token 或更宽权限的凭据。

### Issue Context
该 relay 是 specs PR 的“survived 背书”写回路径;若跨仓读取始终失败,会导致 specs PR 永远无法满足 required adversary check(实际变成永久 fail-closed)。

### Fix Focus Areas
- .github/workflows/adversary-relay.yml[40-63]

### Proposed fix
引入可跨仓读取 CI-Workflows 的最小权限凭据:
- 优先:GitHub App installation token(限制仅 CI-Workflows actions:read + 本仓 checks:write)
- 备选:fine-grained PAT(同样限制仓库范围与 actions:read)
并将该 token 用于 gh/curl 调用 `$AUDIT_REPO` 的读取接口。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +201 to +204
"repository_id": 1337911551,
"path": ".github/workflows/org-gate.yml",
"ref": "main",
"workflows": [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

6. Drift-check 恒报钉点漂移 🐞 Bug ≡ Correctness

expected-state.json 删除 org_required_workflows.ref_commit 并将 ref 改为分支名后,governance/drift-check.sh
仍无条件读取 .ref_commit 并做“钉点移动”比较;由于 WANT_COMMIT 会变成 null,drift-check 会把任何正常状态都判为漂移。
Agent Prompt
### Issue description
`expected-state.json` 中 `org_required_workflows` 已不再包含 `ref_commit`,但 `drift-check.sh` §15 仍执行 `WANT_COMMIT=$(jq -r '.ref_commit' ...)` 并用它与解引用得到的 commit SHA 比较。字段缺失时 `jq -r` 返回 `null`,导致比较恒不相等,从而把 org-required-workflows 误判为“钉点已移动”。

### Issue Context
PR 注释称“内容完整性改由 drift-check 后验承载”,但 drift-check 目前实现仍依赖 `ref_commit`。

### Fix Focus Areas
- governance/drift-check.sh[684-732]
- governance/expected-state.json[197-212]

### Proposed fix
调整 drift-check §15:
- 若 expected-state 不提供 `ref_commit`(或 `ref` 不是 tag/SHA 而是分支名),则不要做 commit-binding 比较;改为:
  - 仅校验 ruleset 的 path/ref/repository_id/workflows 列表一致;并
  - (可选)从分支 ref 解引用到当前 commit,但仅作为信息输出,不作为“移动”漂移判断,或引入新的、可行的完整性机制(例如对 CI-Workflows 工作流文件内容做哈希对账)。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@randypanding
randypanding deleted the fix/cost-check-tar-single-pattern branch August 24, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working feature security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants